package com.ydcode.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;

/**
 * 属性注入
 * 
 * @author YUPENG.LI
 * @version 1.1.0.0
 */
@SuppressWarnings({ "unused", "unchecked", "rawtypes" })
public class BeanUtil {
	/**
	 * 包信息
	 */
	private static HashMap<String, HashMap<String, List<Prototype>>> packageInfoMap = new HashMap<String, HashMap<String, List<Prototype>>>();

	/**
	 * 注入数据
	 * 
	 * @param bean
	 *            需要注入的对象
	 * @param data
	 *            输入的数据
	 * 
	 */
	public static void injectionData(Object bean, JSONObject datas) {
		List<Prototype> prototypes = getProperty(bean.getClass());
		// 遍历注入
		for (Prototype prototype : prototypes) {
			try {
				// 注入BEAN的属性值
				prototype.getSetMethod().invoke(bean,
						getDataByType(datas, prototype));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 注入数据
	 * 
	 * @param cla
	 *            数据类型
	 * @param bean
	 *            要注入的BEAN
	 * @param datas
	 *            JSONObject
	 */
	public static void injectionData(Class cla, Object bean, JSONObject datas) {
		List<Prototype> prototypes = getProperty(cla);
		// 遍历注入
		for (Prototype prototype : prototypes) {
			try {
				// 注入BEAN的属性值
				prototype.getSetMethod().invoke(bean,
						getDataByType(datas, prototype));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 根据数据类型获得对应的数据对象
	 * 
	 * @param datas
	 *            JSONObject
	 * @param prototype
	 *            属性
	 * @return
	 */
	public static Object getDataByType(JSONObject datas, Prototype prototype) {
		Class cla = prototype.getType();
		Object value = datas.get(prototype.getName());
		Object data = null;
		if (value instanceof JSONNull) {
			return null;
		}
		if (cla == Long.class || cla == long.class) {
			data = Long.parseLong(value.toString());
		} else if (cla == String.class || cla == int.class
				|| cla == double.class || cla == Integer.class
				|| cla == Double.class) {
			data = value;
		} else if (cla.isArray()) {
			try {
				// 获得 json 数组
				JSONArray jsonArray = (JSONArray) value;
				// 获得数组类型类
				Class objectClass = Class.forName(cla.getCanonicalName()
						.replace("[]", ""));
				// 获得数组长度
				int size = jsonArray.size();
				// 根据类型获得相应的对象
				if (objectClass == String.class) {
					String[] strings = new String[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						strings[i] = jsonArray.getString(i);
					}
					data = strings;
				} else if (objectClass == Long.class) {
					Long[] longs = new Long[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						longs[i] = jsonArray.getLong(i);
					}
					data = longs;
				} else if (objectClass == long.class) {
					long[] ls = new long[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						ls[i] = jsonArray.getLong(i);
					}
					data = ls;
				} else if (objectClass == double.class) {
					double[] ds = new double[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						ds[i] = jsonArray.getDouble(i);
					}
					data = ds;
				} else if (objectClass == Double.class) {
					Double[] doubles = new Double[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						doubles[i] = jsonArray.getDouble(i);
					}
					data = doubles;
				} else if (objectClass == int.class) {
					int[] is = new int[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						is[i] = jsonArray.getInt(i);
					}
					data = is;
				} else if (objectClass == Integer.class) {
					Integer[] integers = new Integer[size];
					for (int i = 0; i < jsonArray.size(); i++) {
						integers[i] = jsonArray.getInt(i);
					}
					data = integers;
				} else {
					// 其他复杂类型
					Object[] objects = (Object[]) Array.newInstance(
							objectClass, size);
					for (int i = 0; i < jsonArray.size(); i++) {
						JSONObject jsonObject = jsonArray.getJSONObject(i);
						Object obj = getNewInstance(objectClass);
						injectionData(obj, jsonObject);
						objects[i] = obj;
					}
					data = objects;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			try {
				// 复杂类型对象
				// JSONObject.toBean((JSONObject) data, cla);
				data = getNewInstance(cla);
				injectionData(data, (JSONObject) value);
				// injectionData(cla, data, (JSONObject) value);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return data;
	}

	/**
	 * 获得模型的属性
	 * 
	 * @param cla
	 *            类
	 * @return 类的属性信息
	 */
	public static List<Prototype> getProperty(Class cla) {

		String packageName = cla.getPackage().getName();
		String className = cla.getSimpleName();
		HashMap<String, List<Prototype>> beanInfos; // 模型的属性信息
		// 获得包内模型信息数组
		if (packageInfoMap.containsKey(packageName)) {
			beanInfos = packageInfoMap.get(packageName);
		} else {
			beanInfos = new HashMap<String, List<Prototype>>();
			packageInfoMap.put(packageName, beanInfos);
		}
		List<Prototype> prototypes = new ArrayList<Prototype>();
		// 获得获得模型属性信息
		if (beanInfos.containsKey(className)) {
			prototypes = beanInfos.get(className);
		} else {
			// 获得属性信息
			Method[] methods = cla.getMethods();
			for (Method method : methods) {
				if (!method.getName().equals("getClass")
						&& method.getName().startsWith("get")) {
					String name = method.getName().substring(3);
					Method setMethod = null;
					Method getMethod = null;
					try {
						setMethod = cla.getMethod("set" + name,
								method.getReturnType());
						getMethod = cla.getMethod("get" + name);
					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (NoSuchMethodException e) {
						e.printStackTrace();
					}
					if (setMethod != null) {
						Type[] types = method.getParameterTypes();
						if (types.length == 0) {
							Prototype prototype = new Prototype();
							prototype.setName(name.substring(0, 1)
									.toLowerCase() + name.substring(1));
							prototype.setSetMethod(setMethod);
							prototype.setGetMethod(getMethod);
							prototype.setType(method.getReturnType());
							prototypes.add(prototype);
						}
					}
				}
			}
			beanInfos.put(className, prototypes);
		}

		return prototypes;

	}

	// 缓存Instance
	public static HashMap<String, Object> hashMap = new HashMap<String, Object>();

	/**
	 * 
	 * @param cla
	 * @return
	 */
	private static Object getNewInstance(Class cla) {
		Object object = null;
		if (hashMap.containsKey(cla.getName())) {
			object = hashMap.get(cla.getName());
		} else {
			try {
				System.out.println("get");
				object = cla.newInstance();
				hashMap.put(cla.getName(), object);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return object;
	}
}
